/////////////////////////////////////////////////////////////////////////////
// Name:        ax_view.h
// Purpose:     View classes
// Author:      Julian Smart
// Modified by:
// Created:     2009-03-20
// RCS-ID:
// Copyright:   (c) Julian Smart
// Licence:     New BSD License
/////////////////////////////////////////////////////////////////////////////

#ifndef _AX_VIEW_H_
#define _AX_VIEW_H_

/*
 * Includes
 */

#include "ax/ax_property.h"
#include "ax/ax_activator.h"
#include "ax/ax_speech.h"

#include "wx/confbase.h"

/*
 * Forward declarations
 */

class AxMenuItem;
class AxMenu;
class AxMenuItemData;
class AxDocument;
class AxContainerCtrl;
class AxPagerCtrl;
class AxViewManager;
class wxShortcutManager;

/**
  Hints to pass to AxViewManager::UpdateAppearance
 */

enum {
    AxVisualSettingTextSize =           0x0001,
    AxVisualSettingTextColour =         0x0002,
    AxVisualSettingWindowColour =       0x0004,
    AxVisualSettingPanelColour =        0x0008,
    AxVisualSettingAll =                0xFFFF
};

/**
    @class AxVisualSettings
    
    Various visual settings.

    @category{ax}
 */

class AxVisualSettings: public wxObject
{
public:
    AxVisualSettings() { Init(); }
    AxVisualSettings(const AxVisualSettings& info) { Copy(info); }

    void Init();
    void Copy(const AxVisualSettings& info);
    void operator=(const AxVisualSettings& info) { Copy(info); }

    void SetMenuItemDisabledTextColour(const wxColour& col) { m_menuItemDisabledTextColour = col; }
    const wxColour& GetMenuItemDisabledTextColour() const { return m_menuItemDisabledTextColour; }

    void SetMenuItemSelectedTextColour(const wxColour& col) { m_menuItemSelectedTextColour = col; }
    const wxColour& GetMenuItemSelectedTextColour() const { return m_menuItemSelectedTextColour; }

    void SetMenuItemBackgroundColour(const wxColour& col) { m_menuItemBackgroundColour = col; }
    const wxColour& GetMenuItemBackgroundColour() const { return m_menuItemBackgroundColour; }
   
    void SetMenuItemSelectedBackgroundColour(const wxColour& col) { m_menuItemSelectedBackgroundColour = col; }
    const wxColour& GetMenuItemSelectedBackgroundColour() const { return m_menuItemSelectedBackgroundColour; }

#if 0
    void SetMenuItemTextColour(const wxColour& col) { m_menuItemTextColour = col; }
    const wxColour& GetMenuItemTextColour() const { return m_menuItemTextColour; }

    void SetMenuWindowBackgroundColour(const wxColour& col) { m_menuWindowBackgroundColour = col; }
    const wxColour& GetMenuWindowBackgroundColour() const { return m_menuWindowBackgroundColour; }
    
    void SetMenuFont(const wxFont& font) { m_menuFont = font; }
    const wxFont& GetMenuFont() const { return m_menuFont; }
#endif

    /// Sets the general text size for UI elements. If -1, the system font size
    /// will be used.
    void SetTextSize(int sz) { m_textSize = sz; }

    /// Gets the general text size for UI elements. If -1, the system font size
    /// will be used.
    int GetTextSize() const { return m_textSize; }

    /// Gets the specified or default text size
    int GetBestTextSize() const;

    /// Sets the text foreground colour.
    void SetTextColour(const wxColour& col) { m_textColour = col; }

    /// Gets the text foreground colour.
    const wxColour& GetTextColour() const { return m_textColour; }

    /// Gets the specified or default text colour
    wxColour GetBestTextColour() const;

    /// Sets the window background colour, for controls such as text and lists.
    void SetWindowColour(const wxColour& col) { m_windowColour = col; }

    /// Gets the window background colour, for controls such as text and lists.
    const wxColour& GetWindowColour() const { return m_windowColour; }

    /// Gets the specified or default window colour
    wxColour GetBestWindowColour() const;

    /// Sets the panel background colour
    void SetPanelColour(const wxColour& col) { m_panelColour = col; }

    /// Gets the panel background colour
    const wxColour& GetPanelColour() const { return m_panelColour; }

    /// Gets the specified or default panel colour
    wxColour GetBestPanelColour() const;

    /// Load from config
    bool Load(wxConfigBase& config);

    /// Save to config
    bool Save(wxConfigBase& config);

public:    
    wxColour    m_menuItemSelectedTextColour;
    wxColour    m_menuItemDisabledTextColour;
    wxColour    m_menuItemBackgroundColour;
    wxColour    m_menuItemSelectedBackgroundColour;

#if 0
    wxColour    m_menuItemTextColour;
    wxColour    m_menuWindowBackgroundColour;
    wxFont      m_menuFont;
#endif

    int         m_textSize;
    wxColour    m_textColour;
    wxColour    m_windowColour;    // e.g. text, list controls
    wxColour    m_panelColour;
};

/**
    @class AxView
    
    Handles UI for a family of documents, or for a particular data type.

    Override Activate, Deactivate, Initialize, and Uninitialize in your derived class.
    In your Initialize function, create the window(s) and add to the view manager's
    pager control if necessary.

    @category{ax}
 */

class AxView: public wxEvtHandler
{
    DECLARE_CLASS( AxView )

public:
// Constructors

    AxView() { Init(); }
    ~AxView() {}

// Operations

    void Init();

    /// Override to activate the view for a particular document, and show the window.
    virtual bool Activate(AxViewManager* viewManager, AxDocument* doc) = 0;

    /// Override to deactivate the view. This implementation can be empty.
    virtual bool Deactivate(AxViewManager* viewManager) = 0;

    /// Override to create the view's window if necessary. Add the window to the
    /// view manager's pager control.
    virtual bool Initialize(AxViewManager* viewManager) = 0;

    /// Override to uninitialize the view's window. This implementation can be empty.
    virtual bool Uninitialize(AxViewManager* viewManager) = 0;
    
    /// Override to associate the document with the view. By default, calls SetDocument.
    virtual bool AssociateDocument(AxDocument* doc);

    /// Override if something needs to be done before the menu context changes, e.g.
    /// saving an edit. If this returns false, it vetoes the menu change.
    virtual bool OnChangeMenuPre(AxMenu* currentMenu, AxMenu* newMenu);

    /// Override if something needs to be done before the menu context changes, e.g.
    /// saving an edit. If this returns false, it vetoes the menu change.
    virtual bool OnChangeMenuPost(AxMenu* WXUNUSED(newMenu)) { return true; }

    /// Shows the current window in the pager control
    virtual bool ShowWindow(AxViewManager* viewManager);

    /// Get the associated window.
    wxWindow* GetWindow() const { return m_window; }

    /// Set the associated window.
    void SetWindow(wxWindow* window) { m_window = window; }

    /// Get the associated document.
    AxDocument* GetDocument() const { return m_document; }

    /// Set the associated document.
    void SetDocument(AxDocument* doc) { m_document = doc; }

    /// Returns true if active. An active view is one that is currently being shown.
    bool IsActive() const { return m_active; }

    /// Set active.
    void SetActive(bool active) { m_active = active; }

    /// A live view is one that has one or more tasks associated with it
    /// and therefore remains alive in the background. Tasks are not currently
    /// implemented so this doesn't do anything yet.
    bool IsLive() const { return m_live; }
    void SetLive(bool live) { m_live = live; }

    /// Gets the view manager pointer.
    AxViewManager* GetViewManager() const { return m_viewManager; }

    /// Sets the view manager pointer.
    void SetViewManager(AxViewManager* manager) { m_viewManager = manager; }

    /// Gets the speech object.
    AxSpeech* GetSpeech() const;

    /// Say some text
    virtual bool Say(const wxString& text, int flags = AxSpeechFlagsPurge, int verbosity = 2);

    /// Say some text
    virtual bool Say(AxSpeechChannel channel, const wxString& text, int flags = AxSpeechFlagsPurge, int verbosity = 2);

    /// Stop speaking
    virtual bool StopSpeech(AxSpeechChannel channel = AxSpeechDefaultChannel);

    /// Pause or resume speech
    virtual bool PauseOrResumeSpeech(AxSpeechChannel channel = AxSpeechDefaultChannel);

    /// Skip forward
    virtual bool SkipForward(AxSpeechChannel channel = AxSpeechDefaultChannel);

    /// Skip back
    virtual bool SkipBack(AxSpeechChannel channel = AxSpeechDefaultChannel);

    /// Are we speaking?
    virtual bool IsSpeaking(AxSpeechChannel channel = AxSpeechDefaultChannel) const;

    /// Can we stop?
    virtual bool CanStop(AxSpeechChannel channel = AxSpeechDefaultChannel) const;

    /// Can we pause?
    virtual bool CanPause(AxSpeechChannel channel = AxSpeechDefaultChannel) const;

    /// Can we resume?
    virtual bool CanResume(AxSpeechChannel channel = AxSpeechDefaultChannel) const;

    /// Sets the speech channel to be used by this adapter.
    void SetChannel(int channel) { m_channel = channel; }

    /// Returns the speech channel to be used by this adapter.
    AxSpeechChannel GetChannel(AxSpeechChannel channel = AxSpeechDefaultChannel) const;

protected:

    /// An active view is one that is currently being shown.
    bool                m_active;

    /// A live view is one that has one or more tasks associated with it
    /// and therefore remains alive in the background
    bool                m_live;

    wxWindow*           m_window;
    AxDocument*         m_document;
    AxViewManager*      m_viewManager;
    AxSpeechChannel     m_channel;
};

WX_DEFINE_ARRAY_PTR(AxView*, AxViewArray);

/**
    @class AxViewManager
    
    Manages views, documents, and aspects of menu navigation.
    AxViewManager also contains speech objects and visual settings,
    so every AxTk application must store an instance of this class,
    usually in the application class.

    @category{ax}
 */

class AxViewManager: public wxEvtHandler
{
    DECLARE_CLASS( AxViewManager )

public:
// Constructors

    AxViewManager() { Init(); }
    ~AxViewManager();

// Operations

    /// Initialise member variables.
    void Init();

    /// Add a view.
    void AddView(AxView* view) {  m_views.Add(view); }
    
    /// Get view array.
    AxViewArray& GetViews() { return m_views; }

    /// Find view
    AxView* FindView(wxClassInfo* info) const;

    /// Find or create view, and add to view list if necessary
    AxView* FindOrCreateView(wxClassInfo* info);

    /// Activate the specified view.
    virtual bool ActivateView(AxView* view, AxDocument* doc);

    /// Deactive the specified view.
    virtual bool DeactivateView(AxView* view);

    /// Begin/end modal
    virtual bool MakeModal(bool showModal);

    /// Get active view
    AxView* GetActiveView() const { return m_activeView; }

    /// Clear all views.
    void ClearViews();

    /// Clear everything.
    void Clear();

    /// Set the window to be used as the main menu control.
    void SetMenuCtrl(wxWindow* ctrl) { m_menuCtrl = ctrl; }

    /// Get the window used as the main menu control.
    wxWindow* GetMenuCtrl() const { return m_menuCtrl; }

    /// Set the window to be used as the main container control.
    void SetContainerCtrl(AxContainerCtrl* ctrl) { m_containerCtrl = ctrl; }

    /// Get the window used as the main container control.
    AxContainerCtrl* GetContainerCtrl() const { return m_containerCtrl; }

    /// Set the window to be used as the main view pager control.
    void SetViewPagerCtrl(AxPagerCtrl* ctrl) { m_viewPagerCtrl = ctrl; }

    /// Get the window used as the main view pager container control.
    AxPagerCtrl* GetViewPagerCtrl() const { return m_viewPagerCtrl; }

    /// Set the window to be used as the main title control.
    void SetTitleCtrl(wxTextCtrl* ctrl) { m_titleCtrl = ctrl; }

    /// Get the window used as the main title control.
    wxTextCtrl* GetTitleCtrl() const { return m_titleCtrl; }

    /// Set the window to be used as the short description control.
    void SetDescriptionCtrl(wxTextCtrl* ctrl) { m_descriptionCtrl = ctrl; }

    /// Get the window used as the main description control.
    wxTextCtrl* GetDescriptionCtrl() const { return m_descriptionCtrl; }

    /// Get the controller object.
    AxMenuController* GetMenuController() { return m_menuController; }

    /// Set the controller object.
    void SetMenuController(AxMenuController* controller);

    /// Set shortcut manager
    void SetShortcutManager(wxShortcutManager* manager) { m_shortcutManager = manager; }

    /// Get shortcut manager
    wxShortcutManager* GetShortcutManager() const { return m_shortcutManager; }

    /// Show initial top-level menu
    bool ShowInitialMenu(AxMenu* menu);

    /// Show this menu, optionally passing the item it's spawned from.
    /// If @a childMenu is specified, link @a menu but then show the child menu
    /// immediately (i.e., a child of the menu we're showing).
    /// For example, this might be necessary when showing a file selector
    /// with a default selection that is a descendant of the file selection menu.
    bool ShowMenu(AxMenu* menu, AxMenuItem* parentItem = NULL, AxMenu* childMenu = NULL);

    /// Show the home view
    virtual bool ShowHomeView();

    /// Set the home description text
    wxString GetHomeDescription() const { return m_homeDescription; }

    /// Gets the home description text
    void SetHomeDescription(const wxString& descr) { m_homeDescription = descr; }

    /// Returns true if the menu is modal
    bool IsModal() const { return (m_modalCount > 0); }

    /// Get visual settings
    void SetVisualSettings(const AxVisualSettings& settings) { m_visualSettings = settings; }
    AxVisualSettings& GetVisualSettings() { return m_visualSettings; }
    const AxVisualSettings& GetVisualSettings() const { return m_visualSettings; }

    /// Returns the speech object.
    AxSpeech& GetSpeech() { return m_speech; }
    const AxSpeech& GetSpeech() const { return m_speech; }

    /// Updates the appearance of windows when settings changed.
    virtual bool UpdateAppearance(wxWindow* window = NULL, int hints = AxVisualSettingAll);

    /// Stops speaking.
    virtual bool StopSpeech();

    /// Returns true if we can stop speaking.
    virtual bool CanStopSpeech();

    /// Do idle processing. This is actually implemented in the menu controller
    /// in order to strictly control the order of idle processing (speech
    /// idle processing must come last).
    virtual bool IdleProcessing();

    /// Get current instance of the view manager
    static AxViewManager* Get() { return sm_viewManager; }

protected:

    AxViewArray         m_views;
    AxView*             m_activeView;
    wxWindow*           m_menuCtrl;
    AxContainerCtrl*    m_containerCtrl;
    AxPagerCtrl*        m_viewPagerCtrl;
    wxTextCtrl*         m_titleCtrl;
    wxTextCtrl*         m_descriptionCtrl;
    AxMenuController*   m_menuController;
    wxString            m_homeDescription;
    int                 m_modalCount;
    AxVisualSettings    m_visualSettings;
    AxSpeech            m_speech;
    static AxViewManager* sm_viewManager;
    wxShortcutManager*  m_shortcutManager;
};

#endif
    // _AX_VIEW_H_
